#include "pch.hpp"
#include "DocumentWindow.hpp"
#include "Project.hpp"

using namespace Engine;
using namespace Engine::Edit;




DocumentWindow::DocumentWindow(ProjectItem::ptr item, QWidget* parent)
	: QMainWindow(parent)
	, m_state(State::Idle)
	, m_item(item)
	, m_errors(boost::make_shared<ErrorModel>(this))
	, m_dummy(boost::make_shared<char>(0))
{
	m_item->root()->modified.connect(Project::notify::slot_type(&DocumentWindow::itemModified, this, _1, _2, _3).track(m_dummy));

	setTitle();
}
///////////////////////////////////////////////////////////////////////////////////////////////////

DocumentWindow::~DocumentWindow()
{
	emit closed(this);
}
///////////////////////////////////////////////////////////////////////////////////////////////////




ProjectItem::ptr DocumentWindow::item() const
{
	return m_item;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

ErrorModel::const_ptr DocumentWindow::errorModel() const
{
	return m_errors;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void DocumentWindow::changeState(State::Type state)
{
	m_state = state;
}
///////////////////////////////////////////////////////////////////////////////////////////////////




bool DocumentWindow::canBeClosed()
{
	if(isWindowModified())
	{
		QMessageBox msgBox(this);
		msgBox.setText(QString(tr("The document '%1' has been modified.")).arg(m_item->name()));
		msgBox.setInformativeText(tr("Do you want to save your changes?"));
		msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
		msgBox.setDefaultButton(QMessageBox::Save);
		msgBox.setIcon(QMessageBox::Question);
		int ret = msgBox.exec();

		switch (ret)
		{
		case QMessageBox::Save:
			save();
			return true;
		case QMessageBox::Discard:
			// Don't Save was clicked: Close the application without saving
			return true;
		case QMessageBox::Cancel:
			// Cancel was clicked: Don't close the application
			return false;
		default:
			throw programming_error("Unintended path of execution");
		}
	}
	else
	{
		return true;
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////

bool DocumentWindow::closeDocument()
{
	QCloseEvent event;

	QMdiSubWindow* parent = dynamic_cast<QMdiSubWindow*>(this->parent());
	if(parent)
		QApplication::sendEvent(parent, &event);
	else
		QApplication::sendEvent(this, &event);

	return event.isAccepted();
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void DocumentWindow::closeEvent(QCloseEvent* event)
{
	if(canBeClosed())
	{
		event->accept();
		deleteLater();
	}
	else
	{
		event->ignore();
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////

ProjectItem::Result DocumentWindow::itemModified(ProjectItem::weak_ptr _sender, ProjectItem::weak_ptr _item, ProjectItem::Action action)
{
	auto sender = _sender.lock();
	auto item   = _item.lock();

	switch(action)
	{
	case ProjectItem::NameChanged:
		if(sender == m_item)
			setTitle();

		break;
	case ProjectItem::CanRemoveChild:
		// If the item that is about to be removed is the one we are displaying or is one of it's parents,
		// then we must close the view. However we can reject that action in case the user disagrees
		if(item == m_item || item->isParentOf(m_item))
			if(!closeDocument())
				return ProjectItem::Disagree;

		break;
	}

	return ProjectItem::Agree;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void DocumentWindow::setTitle()
{
	setWindowTitle(QString("%1 [*]").arg(m_item->name()));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
